package yf.mall.component.app;

import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import yf.mall.common.Const;
import yf.mall.component.helper.OrderHelper;
import yf.mall.dysdk.model.DyKolOrder;
import yf.mall.dysdk.model.DyKolOrderList;
import yf.mall.dysdk.model.DyToken;
import yf.mall.dysdk.model.request.DyKolOrderRequest;
import yf.mall.dysdk.service.DyAllianceApiService;
import yf.mall.entity.DyAccountAuthEntity;
import yf.mall.entity.KolOrderEntity;
import yf.mall.entity.KolOrderEntityExample;
import yf.mall.entity.custom.PageQuery;
import yf.mall.enums.app.AppDateTypeEnum;
import yf.mall.enums.app.AppOrderDateTypeEnum;
import yf.mall.service.app.DyAccountAuthService;
import yf.mall.service.app.KolOrderService;
import yf.mall.utils.CustomBeanCopier;
import yf.mall.utils.app.AppDateUtil;
import yf.mall.utils.app.AppUtil;
import yf.mall.vo.app.common.ListQuery;
import yf.mall.vo.app.common.ListResult;
import yf.mall.vo.app.order.*;
import yf.mall.vo.app.request.DailyStatisticsRequest;
import yf.mall.vo.app.request.OrderDetailRequest;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;


@Slf4j
@Component
public class AppOrderComponent {

    @Resource
    private AppDyAuthCompoent appDyAuthCompoent;

    @Resource
    private DyAllianceApiService dyAllianceApiService;

    @Resource
    private KolOrderService kolOrderService;

    @Resource
    private DyAccountAuthService dyAccountAuthService;

    private List<DyKolOrder> getKolOrders(Long userId) {
        DyToken dyToken = appDyAuthCompoent.getMasterTokenByUser(userId);
        DyKolOrderRequest request = new DyKolOrderRequest();
        DyKolOrderList kolOrders = dyAllianceApiService.getKolOrders(dyToken, request);
        return kolOrders.getOrders();
    }

    public ListResult<KolOrderVo> getKolOrderList(DailyStatisticsRequest request, Long loginUserId) {
        KolOrderEntityExample example = new KolOrderEntityExample();
        KolOrderEntityExample.Criteria criteria = example.createCriteria();
        if (request.getBegin() != null) {
            criteria.andPaySuccessTimeGreaterThanOrEqualTo(request.getBegin());
        }
        if (request.getEnd() != null) {
            criteria.andPaySuccessTimeLessThanOrEqualTo(request.getEnd());
        }
        List<DyAccountAuthEntity> allAuthByUser = getAllAuthByUserIdAndDisplayId(loginUserId, request.getDisplayId());
        if (allAuthByUser.isEmpty()) {
            return ListResult.emptyResult;
        }
        List<String> openIds = allAuthByUser.stream().map(DyAccountAuthEntity::getOpenId).collect(Collectors.toList());
        criteria.andAuthorOpenidIn(openIds);
        example.setOrderByClause("pay_success_time desc");
        PageInfo<KolOrderEntity> page = kolOrderService.page(example, new PageQuery(request.getPage(), request.getLimit()));
        List<KolOrderEntity> orderEntityList = page.getList();
        if (orderEntityList.isEmpty()) {
            return new ListResult<>(Collections.emptyList(), false);
        }

        List<KolOrderVo> orderVos = OrderHelper.orderEntityListToVo(orderEntityList);

        OrderHelper.fillUserInfo(orderVos, allAuthByUser);

        return new ListResult<>(orderVos, page.isHasNextPage());
    }

    public KolOrderStatVo calKolOrderStatByUser(Long userId, DailyStatisticsRequest dailyStatisticsRequest) {

        Date begin = AppUtil.getBeginByType(dailyStatisticsRequest.getType());
        Date end = AppUtil.getEndByType(dailyStatisticsRequest.getType());

        List<DyAccountAuthEntity> allAuthByUser = getAllAuthByUserIdAndDisplayId(userId, dailyStatisticsRequest.getDisplayId());
        if (allAuthByUser.isEmpty()) {
            return OrderHelper.convertOrderToStat(Collections.emptyList());
        }
        List<DyToken> tokens = allAuthByUser.stream().map(AppDyAuthCompoent::convertToken).collect(Collectors.toList());
        List<KolOrderEntity> userOrders = getKolOrderByTokens(tokens, null, begin, end, AppOrderDateTypeEnum.PAY_TIME.getType());
        return OrderHelper.convertOrderToStat(userOrders);
    }

    public KolOrderDetailStatVo calKolOrderDetailStat(Long userId, OrderDetailRequest request) {

        KolOrderDetailStatVo orderDetailVo = new KolOrderDetailStatVo();
        List<DyAccountAuthEntity> allAuth = getAllAuthByUserIdAndDisplayId(userId, request.getDisplayId());
        if (CollectionUtils.isEmpty(allAuth)) {
            orderDetailVo.setSummaryStatVo(CustomBeanCopier.copy(OrderHelper.convertOrderToStat(Collections.emptyList()), KolOrderStatByProductVo.class));
            orderDetailVo.setTimeStatVo(Collections.emptyList());
            orderDetailVo.setUserStatVo(Collections.emptyList());
            return orderDetailVo;
        }
        List<DyToken> tokens = allAuth.stream().map(AppDyAuthCompoent::convertToken).collect(Collectors.toList());
        Date begin = AppUtil.getBeginByType(request.getType());
        Date end = AppUtil.getEndByType(request.getType());
        List<KolOrderEntity> userOrders = getKolOrderByTokens(tokens, request.getPid(), begin, end, request.getDateType());
        KolOrderStatByProductVo orderStatByProductVo = CustomBeanCopier.copy(OrderHelper.convertOrderToStat(userOrders), KolOrderStatByProductVo.class);
        orderStatByProductVo.setProductId(request.getPid());
        orderDetailVo.setSummaryStatVo(orderStatByProductVo);
        orderDetailVo.setTimeStatVo(buildStatTimeList(userOrders, begin, end, request.getTimeType(), request.getDateType()));
        List<KolOrderStatByUserVo> orderStatByUserVo = OrderHelper.convertOrderToStatByUser(allAuth, userOrders);
        orderDetailVo.setUserStatVo(orderStatByUserVo);

        return orderDetailVo;
    }

    private List<KolOrderStatByTimeVo> buildStatTimeList(List<KolOrderEntity> userOrders, Date begin, Date end, Integer timeType, Integer dataType) {
        if (!Arrays.asList(AppDateTypeEnum.TODAY.getType(), AppDateTypeEnum.YES.getType()).contains(timeType)) {
            timeType = null;
        }

        List<KolOrderStatByTimeVo> kolOrderStatByTimeVos = buildDefaultTimeList(begin, end, timeType);

        List<KolOrderStatByTimeVo> orderStatByTimeVo = OrderHelper.convertOrderToStatByTime(userOrders, dataType, timeType);
        Map<String, KolOrderStatByTimeVo> orderTimeMap = orderStatByTimeVo.stream().collect(Collectors.toMap(o -> o.getTime(), Function.identity()));

        return kolOrderStatByTimeVos.stream().map(timeVo -> {
            if (orderTimeMap.containsKey(timeVo.getTime())) {
                return orderTimeMap.get(timeVo.getTime());
            }
            return timeVo;
        }).collect(Collectors.toList());
    }

    private List<KolOrderStatByTimeVo> buildDefaultTimeList(Date begin, Date end, Integer timeType) {
        List<LocalDateTime> localDateTimes = AppDateUtil.generateTimeListByType(timeType, begin, end);
        return localDateTimes.stream().map(time -> {
            KolOrderStatByTimeVo kolOrderStatByTimeVo = new KolOrderStatByTimeVo();
            kolOrderStatByTimeVo.setLocalDateTime(time);
            if (timeType == null) {
                kolOrderStatByTimeVo.setTime(time.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            } else {
                kolOrderStatByTimeVo.setTime(time.format(DateTimeFormatter.ofPattern("HH:mm")));
            }
            kolOrderStatByTimeVo.setProductId(0L);
            kolOrderStatByTimeVo.setEstimatedCommission("0");
            kolOrderStatByTimeVo.setOrderCount(0L);
            kolOrderStatByTimeVo.setRefundEstimatedCommission("0");
            kolOrderStatByTimeVo.setRefundOrderCount(0L);
            kolOrderStatByTimeVo.setRefundPayAmount("0");
            kolOrderStatByTimeVo.setRefundRatio("0");
            kolOrderStatByTimeVo.setTotalPayAmount("0");
            kolOrderStatByTimeVo.setValidEstimatedCommission("0");
            kolOrderStatByTimeVo.setValidOrderCount(0L);
            kolOrderStatByTimeVo.setValidPayAmount("0");
            return kolOrderStatByTimeVo;
        }).collect(Collectors.toList());
    }

    private List<DyAccountAuthEntity> getAllAuthByUserIdAndDisplayId(Long userId, String displayId) {
        if (StringUtils.isNotBlank(displayId)) {
            DyAccountAuthEntity dyAccountAuthEntity = dyAccountAuthService.getAuthByUserAndDisplayId(userId, displayId);
            return dyAccountAuthEntity != null ? Collections.singletonList(dyAccountAuthEntity) : Collections.emptyList();
        } else {
            return dyAccountAuthService.getAllAuthByUser(userId);
        }
    }

    public int notifyOrderData(DyToken token, DyKolOrder dyKolOrder) {
        if (token == null || dyKolOrder == null) {
            return 0;
        }
        Long orderId = dyKolOrder.getOrderId();
        KolOrderEntity kolOrderEntity = OrderHelper.convertDyToDb(dyKolOrder);
        KolOrderEntity dbOrder = kolOrderService.get(orderId);
        int result;
        if (dbOrder == null) {
            result = kolOrderService.save(kolOrderEntity);
        } else {
            result = kolOrderService.update(kolOrderEntity);
        }
        return result;
    }


    private List<KolOrderEntity> getKolOrderByTokens(List<DyToken> tokens, Long pid, Date begin, Date end, Integer dateType) {
        if (Objects.equals(AppOrderDateTypeEnum.PAY_TIME.getType(), dateType)) {
            return kolOrderService.getKolOrderByPayTime(tokens, pid, begin, end);
        } else if (Objects.equals(AppOrderDateTypeEnum.SETTLE_TIME.getType(), dateType)) {
            return kolOrderService.getKolOrderBySettleTime(tokens, pid, begin, end);
        }
        return kolOrderService.getKolOrderByPayTime(tokens, pid, begin, end);
    }

    public KolOrderDetailVo orderDetail(Long userId, OrderDetailRequest request) {
        KolOrderEntity kolOrderEntity = kolOrderService.get(request.getOrderId());
        KolOrderVo orderVo = OrderHelper.convert(kolOrderEntity);
        KolOrderDetailVo kolOrderDetailVo = CustomBeanCopier.copy(orderVo, KolOrderDetailVo.class);
        List<DyAccountAuthEntity> allAuthByUser = dyAccountAuthService.getAllAuthByUser(userId);
        OrderHelper.fillUserInfo(Collections.singletonList(kolOrderDetailVo), allAuthByUser);

        List<String> openIds = allAuthByUser.stream().map(DyAccountAuthEntity::getOpenId).collect(Collectors.toList());
        Long orderNum = kolOrderService.countOrders(openIds, kolOrderEntity.getProductId());
        BigDecimal totalPayAmount = kolOrderService.countOrderTotalPayAmount(openIds, kolOrderEntity.getProductId());
        BigDecimal totalCommission = kolOrderService.countOrderEstimatedTotalCommission(openIds, kolOrderEntity.getProductId());
        kolOrderDetailVo.setProductOrderNum(orderNum.toString());
        kolOrderDetailVo.setProductTotalPayAmount(totalPayAmount.divide(Const.HUNDRED, 2, RoundingMode.HALF_DOWN).toString());
        kolOrderDetailVo.setProductTotalKolCosFee(totalCommission.divide(Const.HUNDRED, 2, RoundingMode.HALF_DOWN).toString());
        return kolOrderDetailVo;
    }
}
